const { Service } = require('egg');
const { v4 } = require('uuid');
const fse = require('fs-extra');
const path = require('path');
const moment = require('moment');

const mfs = require('mz/fs');
const pump = require('mz-modules/pump');

const table_name = 'file';
class FileService extends Service {

  async upload() {
    const ctx = this.ctx;
    const trx = await ctx.app.knex.transaction();
    const result = [];
    try {
      const { id: user_id } = ctx.session;
      const files = ctx.request.files;
      const time = moment();

      if (files.length < 1) {
        throw new Error('文件不能为空');
      }
      const dirpath = await ctx.service.folder.targetDir();

      const cloud = await ctx.service.cloud.getDefault();

      if (cloud.type === 'LOCAL') {
        await this.localUpload(files, dirpath, cloud.uuid, user_id, time, result, trx);
      }

      await trx.commit();

      return result;
    } catch (error) {
      await trx.rollback();
      if (result.length > 0) {
        result.forEach(f => {
          fse.removeSync(f.url);
        });
      }
      throw error;
    } finally {
      await ctx.cleanupRequestFiles();
    }
  }

  async localUpload(files, dirPath, cloud_id, user_id, time, save_file, trx) {
    const ctx = this.ctx;
    const list = [];
    try {
      // 文件上传处理
      for (const file of files) {
        const filename = file.filename;
        const uuid = v4().replace(/-/g, '');
        const fileExtension = filename.split('.').pop();
        // file.filepath = path.join(dirPath, `${uuid}.${fileExtension}`);
        const targetPath = path.join(dirPath, `${uuid}.${fileExtension}`);

        const source = mfs.createReadStream(file.filepath);

        const target = mfs.createWriteStream(targetPath);


        await pump(source, target);
        list.push(targetPath);

        const instance = {
          uuid: v4(),
          name: filename,
          size: file.size,
          type: ctx.app.config.filetype.get(fileExtension.toUpperCase()) ? ctx.app.config.filetype.get(fileExtension.toUpperCase()) : 'UNDEFINED',
          url: targetPath.replace('app/public'),
          file_cloud: cloud_id,
          create_time: moment(time).format('YYYY-MM-DD HH:mm:ss'),
          update_time: moment(time).format('YYYY-MM-DD HH:mm:ss'),
          create_by: user_id ? user_id : '-1',
          update_by: user_id ? user_id : '-1',
          is_delete: 0,
        };
        await trx(table_name).insert(instance);
        save_file.push(instance);
      }
    } catch (error) {

      if (list.length > 0) {
        for (const l of list) {
          fse.removeSync(l);
        }
      }

      throw error;
    }
  }

  async removeLocalFiles(ids) {
    const ctx = this.ctx;
    try {
      const urls = await ctx.app.knex(table_name).select('url').whereIn('uuid', ids);

      for (const url of urls) {
        const basepath = path.join(ctx.app.config.root_path, url);
        fse.removeSync(basepath);
      }

      const data = await ctx.app.knex(table_name).del().whereIn('uuid', ids)
        .returning('uuid');

      return data;
    } catch (error) {
      throw error;
    }
  }
}

module.exports = FileService;
